widget: Improve hack to ignore drags from widgets using motion events
authorCarlos Garnacho <carlosg@gnome.org>
Tue, 3 Mar 2015 21:17:58 +0000 (22:17 +0100)
committerMatthias Clasen <mclasen@redhat.com>
Thu, 5 Mar 2015 02:20:29 +0000 (21:20 -0500)
Postpone until the last moment whether the target widget still
potentially uses updates from this sequence, or window dragging
actually applies because all gestures on the target went to denied
state.

This fixes window dragging on empty space in a headerbar that is
contained in a paned (as in e.g. gedit).

https://bugzilla.gnome.org/show_bug.cgi?id=745562

gtk/gtkwidget.c
gtk/gtkwidgetprivate.h
gtk/gtkwindow.c

index c50b68476e7afa860b8d3b2ec36901a7f630995e..715105d9a7dc0b6a30f860654b4984fa60326292 100644 (file)
@@ -17284,7 +17284,8 @@ _gtk_widget_list_controllers (GtkWidget           *widget,
 }
 
 gboolean
-_gtk_widget_consumes_motion (GtkWidget *widget)
+_gtk_widget_consumes_motion (GtkWidget        *widget,
+                             GdkEventSequence *sequence)
 {
   EventControllerData *data;
   GtkWidgetPrivate *priv;
@@ -17301,10 +17302,11 @@ _gtk_widget_consumes_motion (GtkWidget *widget)
       if (data->controller == NULL)
         continue;
 
-      if (!GTK_IS_GESTURE_SINGLE (data->controller))
-        return TRUE;
-      else if (GTK_IS_GESTURE_DRAG (data->controller) ||
-               GTK_IS_GESTURE_SWIPE (data->controller))
+      if ((!GTK_IS_GESTURE_SINGLE (data->controller) ||
+           GTK_IS_GESTURE_DRAG (data->controller) ||
+           GTK_IS_GESTURE_SWIPE (data->controller)) &&
+          gtk_gesture_get_sequence_state (GTK_GESTURE (data->controller),
+                                          sequence) != GTK_EVENT_SEQUENCE_DENIED)
         return TRUE;
     }
 
index 676d6e856c90be49d4a4b137e050afd582f00b09..7f121aa1288c1c69ab8498251db3e84d9c945616 100644 (file)
@@ -160,7 +160,8 @@ void              _gtk_widget_remove_controller            (GtkWidget
                                                             GtkEventController  *controller);
 GList *           _gtk_widget_list_controllers             (GtkWidget           *widget,
                                                             GtkPropagationPhase  phase);
-gboolean          _gtk_widget_consumes_motion              (GtkWidget           *widget);
+gboolean          _gtk_widget_consumes_motion              (GtkWidget           *widget,
+                                                            GdkEventSequence    *sequence);
 
 gboolean          gtk_widget_has_tick_callback             (GtkWidget *widget);
 
index ba79229d6b25c35054ecda392910634f281dcd89..92d7a03cdea78c1dfda0b19b3dd29e855635661d 100644 (file)
@@ -1509,7 +1509,6 @@ drag_gesture_begin_cb (GtkGestureDrag *gesture,
   GdkEventSequence *sequence;
   GtkWindowRegion region;
   const GdkEvent *event;
-  GtkWidget *event_widget;
 
   sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
   event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), sequence);
@@ -1517,19 +1516,10 @@ drag_gesture_begin_cb (GtkGestureDrag *gesture,
   if (!event)
     return;
 
-  event_widget = gtk_get_event_widget ((GdkEvent *) event);
+  region = get_active_region_type (window, (GdkEventAny*) event, x, y);
 
-  if (event_widget != GTK_WIDGET (window) &&
-      !gtk_widget_has_grab (event_widget) &&
-      _gtk_widget_consumes_motion (event_widget))
+  if (region != GTK_WINDOW_REGION_TITLE)
     gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
-  else
-    {
-      region = get_active_region_type (window, (GdkEventAny*) event, x, y);
-
-      if (region != GTK_WINDOW_REGION_TITLE)
-        gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
-    }
 }
 
 static void
@@ -1549,8 +1539,23 @@ drag_gesture_update_cb (GtkGestureDrag *gesture,
   if (ABS (offset_x) > double_click_distance ||
       ABS (offset_y) > double_click_distance)
     {
+      GdkEventSequence *sequence;
       gdouble start_x, start_y;
       gint x_root, y_root;
+      const GdkEvent *event;
+      GtkWidget *event_widget;
+
+      sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
+      event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), sequence);
+      event_widget = gtk_get_event_widget ((GdkEvent *) event);
+
+      if (event_widget != GTK_WIDGET (window) &&
+          !gtk_widget_has_grab (event_widget) &&
+          _gtk_widget_consumes_motion (event_widget, sequence))
+        {
+          gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
+          return;
+        }
 
       gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);